package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.BloomType;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.search.SkuEsFeignClient;
import com.atguigu.gmall.model.list.Goods;
import com.atguigu.gmall.model.list.SearchAttr;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.SkuInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.netflix.hystrix.ExecutionResult;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    SkuInfoMapper skuInfoMapper;

    @Autowired
    SkuImageMapper skuImageMapper;

    @Autowired
    SkuAttrValueMapper skuAttrValueMapper;

    @Autowired
    SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Autowired
    RedissonClient redissonClient;

    @Qualifier(BloomType.SKU)
    @Autowired
    RBloomFilter<Object> skuFilter;

    @Autowired
    SkuEsFeignClient skuEsFeignClient;

    @Autowired
    BaseTrademarkMapper baseTrademarkMapper;

    @Autowired
    BaseCategory3Mapper baseCategory3Mapper;

    @Autowired
    BaseCategory2Mapper baseCategory2Mapper;

    @Autowired
    BaseCategory1Mapper baseCategory1Mapper;

    @Qualifier(value = "corePool")
    @Autowired
    ThreadPoolExecutor executor;

    /**
     * 保存SKU信息
     * @param skuInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveSkuInfo(SkuInfo skuInfo) {

        //1、保存skuinfo的基本信息
        int insert = skuInfoMapper.insert(skuInfo);
        Long skuId = skuInfo.getId();

        //2、保存sku图片信息
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        if (!CollectionUtils.isEmpty(skuImageList)){
            for (SkuImage skuImage : skuImageList) {
                skuImage.setSkuId(skuId);
                skuImageMapper.insert(skuImage);
            }
        }

        //3、保存sku的平台属性对应的所有值sku_attr_value
        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)){
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuId);
                skuAttrValueMapper.insert(skuAttrValue);
            }
        }

        //4、保存sku的销售属性以及值信息sku_sale_attr_value
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        if (!CollectionUtils.isEmpty(skuSaleAttrValueList)){
            for (SkuSaleAttrValue skuSaleAttrValue : skuSaleAttrValueList) {
                skuSaleAttrValue.setSkuId(skuId);
                skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
                skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            }
        }
        /**
         * TODO 组装skuKey并加入布隆
         */
        String skuKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
        skuFilter.add(skuKey);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean onSale(Long skuId) {
        //上架是修改数据库
        boolean b = skuInfoMapper.updateSkuSaleStatus(skuId,1);

        //TODO 2、 把商品信息同步到搜索引擎
        Goods goods = new Goods();

        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            //1、封装基本信息
            SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
            goods.setId(skuInfo.getId());
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
            goods.setTitle(skuInfo.getSkuName());
            return skuInfo;
        },executor);

        CompletableFuture<Void> priceFuture = CompletableFuture.runAsync(() -> {
            //2、封装价格
            BigDecimal price = skuInfoMapper.selectSkuPriceBySkuId(skuId);
            goods.setPrice(price);
        }, executor);

        CompletableFuture<Void> trademarkFuture = CompletableFuture.runAsync(() -> {
            //goods.setCreateTime(new Date());//不在这里准备时间，以es的处理为准
            //3、封装品牌信息
            BaseTrademark baseTrademark = baseTrademarkMapper.getBaseTradeBySkuId(skuId);
            goods.setTmId(baseTrademark.getId());
            goods.setTmName(baseTrademark.getTmName());
            goods.setTmLogoUrl(baseTrademark.getLogoUrl());
        }, executor);

        CompletableFuture<Void> baseCategory3Future = skuInfoFuture.thenAcceptAsync(skuInfo -> {
            //4、封装分类
            BaseCategory3 baseCategory3 = baseCategory3Mapper.selectById(skuInfo.getCategory3Id());
            goods.setCategory3Id(baseCategory3.getId());
            goods.setCategory3Name(baseCategory3.getName());

            BaseCategory2 baseCategory2 = baseCategory2Mapper.selectById(baseCategory3.getCategory2Id());
            goods.setCategory2Id(baseCategory2.getId());
            goods.setCategory2Name(baseCategory2.getName());

            BaseCategory1 baseCategory1 = baseCategory1Mapper.selectById(baseCategory2.getCategory1Id());
            goods.setCategory1Id(baseCategory1.getId());
            goods.setCategory1Name(baseCategory1.getName());
        }, executor);

        //CompletableFuture.runAsync(()->{
        //    //5、热度分
        //    goods.setHotScore(0L);
        //});

        CompletableFuture<Void> searchAttrsFuture = CompletableFuture.runAsync(() -> {
            //6、当前sku对应的所有的平台属性以及值
            List<SearchAttr> searchAttrs = skuAttrValueMapper.getBaseAttrAndValueBySkuId(skuId);
            goods.setAttrs(searchAttrs);
        },executor);

        CompletableFuture<Void> future = CompletableFuture
                .allOf(skuInfoFuture, priceFuture, trademarkFuture, baseCategory3Future, searchAttrsFuture);
        future.whenCompleteAsync((res,exc)->{
            // 远程调用检索事务，保存到es
            skuEsFeignClient.saveSkuToEs(goods);
        },executor);


        return b;
    }

    @Override
    public boolean cancelSale(Long skuId) {
        //下架是修改数据库
        boolean b = skuInfoMapper.updateSkuSaleStatus(skuId,0);

        CompletableFuture.runAsync(()->{
            //TODO 2、 把商品信息从搜索引擎中移除
            skuEsFeignClient.delSkuToEs(skuId);
        },executor);
        return b;
    }

    /**
     * 查数据库中所有的skuId
     * @return
     */
    @Override
    public List<Long> getAllId() {
        return skuInfoMapper.getAllSkuId();
    }
}
